package io.github.uicdb.badskill.clent.impl;

import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import io.github.uicdb.badskill.*;
import io.github.uicdb.badskill.clent.AbstractScrollPanel;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class SkillPagePanel extends AbstractScrollPanel {
    @Getter
    @Setter
    protected SkillPage currentPage;
    @Nullable
    public ResourceLocation selectedID = null;
    protected final PlayerSkillCapability capability;
    protected static final ResourceLocation CONNECTION = new ResourceLocation(BadSkill.MODID, "textures/gui/connection.png");
    public static final ResourceLocation NULL_ICON =new ResourceLocation(BadSkill.MODID,"textures/gui/unknown_icon.png");
    public static final ResourceLocation NULL_SKILL_LEARNED =new ResourceLocation(BadSkill.MODID,"textures/gui/unknown_learned_icon.png");
    public SkillPagePanel(int pX, int pY, int pWidth, int pHeight, double scaleMin, double scaleMax) {
        super(pX, pY, pWidth, pHeight, scaleMin, scaleMax);
        this.currentPage = SkillPageManager.INSTANCE.safeGet(0);
        capability = Minecraft.getInstance().player.getCapability(PlayerSkillCapabilityProvider.CAPABILITY).resolve().orElseThrow();
        scrollToCenter();
    }

    public void reload(int id) {
        this.currentPage = SkillPageManager.INSTANCE.safeGet(id);
        this.relativeX =0;
        this.relativeY =0;
        this.scale=1;
        selectedID=null;
        scrollToCenter();
    }

    @Override
    protected void renderToolTip(GuiGraphics guiGraphics, int pMouseX, int pMouseY) {
        currentPage.locations.forEach((resourceLocation, location) -> {
            if (isHitChild(location,pMouseX,pMouseY)) {
                assert Minecraft.getInstance().screen != null;
                SkillOption option = SkillOptionManager.INSTANCE.OPTIONS.get(resourceLocation);
                PlayerSkillCapability.State state = capability.checkState(location, option);
                List<Component> components = new ArrayList<>();
                components.add(state.getTip());
                guiGraphics.renderTooltip(Minecraft.getInstance().font, components.stream().map(Component::getVisualOrderText).collect(Collectors.toList()), pMouseX, pMouseY);
            }
        });
    }
    protected boolean isHitChild(SkillPage.Location location, double pMouseX, double pMouseY){
        return  pMouseX > getHitX(location.x) && pMouseX < getHitX(location.x + location.width) && pMouseY > getHitY(location.y) && pMouseY < getHitY(location.y + location.height);
        }

    @Override
    protected void renderBg(GuiGraphics guiGraphics, Minecraft instance, int pMouseX, int pMouseY) {
        if (currentPage.background != null) {
            guiGraphics.blit(currentPage.background, getX(), getY(), 0, 0, getWidth(), getHeight(), getWidth(), getHeight());
        }
    }

    @Override
    protected void onPanelClick(double pMouseX, double pMouseY, int pButton) {
        for (Map.Entry<ResourceLocation, SkillPage.Location> entry : currentPage.locations.entrySet()) {
            ResourceLocation resourceLocation = entry.getKey();
            SkillPage.Location location = entry.getValue();
            if (isHitChild(location,pMouseX,pMouseY)) {
                selectedID=resourceLocation;
                return;
            }
        }
    }

    @Override
    public void render(@NotNull GuiGraphics guiGraphics, int pMouseX, int pMouseY, float pPartialTick) {
        RenderSystem.enableBlend();
        RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
        RenderSystem.disableDepthTest();
        renderBg(guiGraphics, Minecraft.getInstance(), pMouseX, pMouseY);
        guiGraphics.enableScissor(getX(), getY(), getX() + width, getY() + height);

        if (currentPage.imageLocations != null) {
            currentPage.imageLocations.forEach(imageLocation -> {
                guiGraphics.pose().pushPose();
                guiGraphics.pose().scale(scale,scale,scale);
                guiGraphics.pose().translate(-relativeX + imageLocation.x+getX(), -relativeY + imageLocation.y+getY(), 1);
                guiGraphics.blit(imageLocation.location, 0, 0, 0, 0, (int) (imageLocation.width), (int) (imageLocation.height), (int) (imageLocation.width), (int) (imageLocation.height));
                guiGraphics.pose().popPose();
            });
        }
        if (currentPage.locations != null) {
            currentPage.locations.forEach((resourceLocation, location) -> {
                for (ResourceLocation parent : location.parents) {
                    var ol = currentPage.locations.get(parent);
                    renderConnection(guiGraphics, location.x+location.width/2f, location.y+location.height/2f, ol.x+ol.width/2f, ol.y+ol.height/2f, selectedID != null && selectedID.equals(resourceLocation), pPartialTick);
                }
            });
        }
        if (currentPage.locations != null) {
            currentPage.locations.forEach((id, location) -> {
                guiGraphics.pose().pushPose();
                guiGraphics.pose().scale(scale,scale,scale);
                guiGraphics.pose().translate(-relativeX + location.x+getX(), -relativeY + location.y+getY(), 1);
                var state=capability.checkState(location,SkillOptionManager.INSTANCE.OPTIONS.get(id));
                if(!(state== PlayerSkillCapability.State.LEARNABLE||state== PlayerSkillCapability.State.LEARNED)){
                    RenderSystem.setShaderColor(139f/255f,139f/255f,131f/255f,1);
                }
                ResourceLocation ic=NULL_ICON;
                if(state== PlayerSkillCapability.State.LEARNED)
                    ic=location.learnedIcon==null?NULL_SKILL_LEARNED:location.learnedIcon;
                else {
                    if(location.icon!=null)ic=location.icon;
                }
                guiGraphics.blit(ic, 0, 0, 0, 0, (int) (location.width), location.height, location.width, location.height);
                RenderSystem.setShaderColor(1,1,1,1);
                guiGraphics.pose().popPose();
            });
        }
        guiGraphics.disableScissor();
        renderToolTip(guiGraphics, pMouseX, pMouseY);
        RenderSystem.disableBlend();
        RenderSystem.enableDepthTest();
    }

    @Override
    protected void renderWidget(@NotNull GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {

    }

    int tick;

    private void renderConnection(GuiGraphics guiGraphics, float connectionX, float connectionY, float x2, float y2, boolean isSelected, float pPartialTick) {
        PoseStack poseStack = guiGraphics.pose();
        poseStack.pushPose();
        poseStack.scale(scale,scale,scale);
        poseStack.translate(-relativeX + connectionX + getX(), -relativeY + connectionY + getY(), 0);
        var rotation = getAngleBetweenPoints(connectionX, connectionY, x2, y2);
        poseStack.mulPose(Axis.ZP.rotation(rotation));
        int length = (int) getDistanceBetweenPoints(connectionX, connectionY, x2, y2);
        if (tick > 45) tick = 1;
        guiGraphics.blit(CONNECTION, 0, -3, length, 6, Mth.lerp(pPartialTick, 0, (isSelected ? tick : 0)), 0, length, 6, 45, 6);
        tick++;
        poseStack.popPose();
    }

    protected float getDistanceBetweenPoints(float x1, float y1, float x2, float y2) {
        return Mth.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
    }

    protected float getAngleBetweenPoints(float x1, float y1, float x2, float y2) {
        return (float) Mth.atan2(y2 - y1, x2 - x1);
    }
}
